home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Network Support Library
/
RoseWare - Network Support Library.iso
/
apidev
/
envp.arc
/
ENVP.C
next >
Wrap
Text File
|
1989-01-15
|
10KB
|
368 lines
#include <stdio.h>
#include <stdlib.h>
#include <dos.h>
#include <fcntl.h>
#include <types.h>
#include <stat.h>
#include <string.h>
#include <dos.h>
#include <direct.h>
/* $$cc: -w3 -nh */
/*
(c) Cyco software, the Netherlands, januari 1989
Routines to handle the environment of the parent proces.
A normal DOS process only gets a copy of the original environment.
Any changes made to that environment are only accessable to child
programs (programs that the parent program runs).
These routines may be used to change the environment of the parent.
In most cases the parent process is COMMAND.COM, so with these
routines you can build your own dos 'SET' statement.
The example included at the bottom sets the current drive and
directory in the environment variables DRV and CWD. In batch
files they can be used with the %DRV% and %CWD% method.
This code should be compiled with Microsoft C5 compiler. Any
memory model should work properly.
This program code may be copied and changed for own use as long
as the copyright line in top is maintained. Any comments please
reply them to me:
Bart Mellink
Cyco Automation
Adm. Banckertweg 2a
2315 SR Leiden
The Netherlands
phone: (int)-31-71-222707
fax: (int)-31-71-224979
compuserve easyplex 76702,256
*/
#define OK 0
#define ERROR -1
#define TRUE 1
#define FALSE 0
/*------------------------- code ------------------------*/
unsigned ParentEnvseg(void) {
char far *p;
unsigned parseg;
static unsigned parentenv = 0;
/* Get segment address of Parents Environment.
In our own PSP there is a undocumented pointer to the PSP
of the parent proces at offset 16-hex.
In most processes we can find a pointer to the environment
at offset 2C in the PSP. For command.com itself (that is
mostly our parent) this holds only for DOS 3.30, so we
have to find another way.
*/
if (parentenv != 0) /* we allready did this routine before */
return parentenv;
FP_SEG(p) = _psp;
FP_OFF(p) = 0;
parseg = *(unsigned far *)(p+0x016);
/* Try an alternative way to get the segment of the parent's
environment. We allready have the segment of the parent program
in parseg. Mostly one segment (16 bytes) before that segment
is the DOS malloc infoblock of that segment. By following the
DOS malloc chain we can find the environment.
The DOS malloc info block consists of:
4D -- code (last one is 5a)
WORD -- segment of owner (should be running command.com)
but can be zero in case of an orphan block
WORD -- number of segments of that block
*/
FP_SEG(p) = parseg - 1; /* previous segment */
FP_OFF(p) = 0;
if ((*p != 0x4d) || (parseg != * (unsigned far *)(p+1)))
return 0; /* can't find it */
FP_SEG(p) += * (unsigned far *)(p+3) + 1; /* next block */
while ((*p == 0x4d) && (parseg != * (unsigned far *)(p+1))) {
FP_SEG(p) += * (unsigned far *)(p+3) + 1; /* next block */
}
if (*p != 0x4d)
return 0;
parentenv = (FP_SEG(p) + 1);
return parentenv;
}
char far * ParentEnv(void) {
char far *p;
/* Returns far pointer to the parents environment */
FP_SEG(p) = ParentEnvseg();
FP_OFF(p) = 0;
return p;
}
unsigned ParentEnvMaxSize(void) {
union REGS inregs, outregs;
struct SREGS segregs;
/* The environment is a DOS allocatable block, so we use
the dos setblock function to set the size to maximum.
(dos return number of segments).
Then we have the environment size we can max use.
Works only for small blocks (<64k), but the environment
is mostly smaller, so that's no point.
This routine returns number of bytes that can be max in environ-
ment.
*/
inregs.h.ah = 0x04a; /* function */
inregs.x.bx = 0x08000; /* try large space */
segregs.es = ParentEnvseg(); /* segment address */
if (segregs.es == 0) /* illegal */
return 0;
int86x(0x021, &inregs, &outregs, &segregs);
return (outregs.x.bx * 16);
}
unsigned ParentEnvSize(void) {
char far *p;
unsigned i=2; /* at least 2 nulls */
/* Calculate the space of the parents environment. The
environment consists of multiple strings that are null
terminated. A double null is the end of the environment.
*/
p = ParentEnv();
if (p==NULL)
return 0;
while ((*p!='\0') || (*(p+1)!='\0')) {
i++; p++;
}
return i;
}
unsigned ParentEnvFree(void) {
/* returns free space in environment */
return ParentEnvMaxSize() - ParentEnvSize();
}
static int farstrncmp(char * nearstr, char far * farstr) {
/* string compare working on one far pointer
Returns TRUE or FALSE.
Returns TRUE if all characters in the nearstring are
the same as the first ones in the farstring.
*/
while (*nearstr && *farstr) {
if (*nearstr++ != *farstr++) return FALSE;
}
if (*nearstr)
return FALSE; /* farstring too short */
else
return TRUE;
}
static unsigned farstrlen(char far * str) {
unsigned i = 0;
while (*str++) i++;
return i;
}
static int cinstr(char *p, char c) {
int i=0;
/* look if character c is inside string p */
while (*p) {
if (*p == c) return i;
p++; i++;
}
return ERROR;
}
/* --------------- the most important routines -------------------- */
char far * ParentGetenv(char * varname) {
char far *p;
/* Look if the variable varname is in the environment
of the parent process.
If yes return pointer to the string (far pointer!).
If not return NULL.
This routine is a little different from the microsoft lib
version: it returns a far pointer, because the environment
can be anywhere in memory.
*/
p = ParentEnv();
if (p==NULL)
return NULL;
while ((*p!='\0') || (*(p+1)!='\0')) {
if (*p == '\0')
p++;
if (farstrncmp(varname, p) && (*(p+strlen(varname))=='=')) {
return (p+strlen(varname)+1);
}
while (*p)
p++;
}
return NULL;
}
int ParentPutenv(char * envstr) {
/* Put the string envstr in the environment of the parent
process. The envstr normally has a NAME=STRING syntax.
In that case it replaces the old NAME= value in the
environment.
If however the NAME= syntax is not used, the bare string
is placed in the environment. This has normally no use, but
for the sake of compatibility with the microsoftlib version
of 'putenv'.
Returns:
If the environment is full ERROR is returned otherwise OK.
Side effect:
The NAME= part is converted to upper case (as it should be)
*/
char *q, *substr;
char far *p = ParentEnv();
char far *p2;
unsigned envstrlen = strlen(envstr);
if (p==NULL)
return ERROR;
if (cinstr(envstr, '=') != ERROR) {
/* we have a '=' sign there */
q = envstr;
while (*q != '=') {
*q = (char) toupper(*q);
q++;
}
*q = '\0'; /* split temporary for getenv() function */
substr = q+1; /* pointer behind "=" in envstr */
if ((p = ParentGetenv(envstr)) != NULL) {
/* we know the string is allready there, calc size */
if (strlen(substr)+1 > farstrlen(p)+ParentEnvFree()) {
*q = '='; /* restore old envstr */
return ERROR; /* no room */
}
/* now delete old string */
p -= (strlen(envstr)+1); /* begin of old parent string */
p2 = p + farstrlen(p); /* end of string (null char) */
while ((*p2!='\0') || (*(p2+1)!='\0')) {
*p++ = *(p2+1);
p2++;
}
*p = '\0';
/* test if substring is empty (remove from env) */
if (strlen(substr)==0) {
*q = '='; /* restore old envstr */
return OK;
}
}
*q = '='; /* restore old envstr */
}
/* look if we have enough room */
if (strlen(envstr)+1 > ParentEnvFree())
return ERROR;
/* set pointer at end of parent environment and copy string */
p = ParentEnv() + ParentEnvSize() - 1;
while (*envstr) {
*p++ = *envstr++;
}
*p ++ = '\0'; /* add a double null */
*p ++ = '\0';
return OK;
}
/* ---------------------- test program ----------------------- */
void main(int argc, char **argv) {
char far *p;
unsigned envmaxsize;
int i;
char buf1[80], buf2[80];
printf("(c) `88 Cyco Software, the Netherlands.\n");
p = ParentEnv();
envmaxsize = ParentEnvMaxSize();
printf("PSP (our) = %x (hex)\n", _psp);
printf("ENV of parent = %x (hex)\n", ParentEnvseg());
printf("ENV max size = %d bytes\n", envmaxsize);
printf("ENV size = %d bytes\n", ParentEnvSize());
printf("ENV free = %d bytes\n", ParentEnvFree());
printf("\n");
/* print here the environment */
for (i=0; i<envmaxsize; i++) {
if (*p == 0) {
p++; printf("\n");
if (*p == 0) {
break;
}
}
else {
putchar(*p++);
}
}
/* put the current drive in DRV and directory in CWD */
if (getcwd(buf1, 79) != NULL) {
sprintf(buf2, "CWD=%s", buf1+2);
printf("\nErrorcode putenv --%s-- is %d", buf2, ParentPutenv(buf2));
sprintf(buf2, "DRV=%c:", *buf1);
printf("\nErrorcode putenv --%s-- is %d", buf2, ParentPutenv(buf2));
}
if (argc==1) {
printf("\nFirst argument is passed to getenv, second to putenv.");
}
if (argc>1) {
p = ParentGetenv(argv[1]);
if (p==NULL)
printf("Can't find --%s-- in environment\n", argv[1]);
else {
printf("String of environment variable %s = ", argv[1]);
while (*p)
putchar(*p++);
}
printf("\n\n");
}
if (argc>2) {
printf("Putenv --%s-- returns code %d\n", argv[2], ParentPutenv(argv[2]));
}
}